
// CUniqNumGenerater.cpp
//

#include "StdAfx.h"
#include "UniqNumGenerater.h"
#include "LogService.h"

UniqNumGenerater::UniqNumGenerater(){
	bitset_ = 0;
}

UniqNumGenerater::~UniqNumGenerater(){
	SAFE_DELETE( bitset_ );
}

bool UniqNumGenerater::initialize( unsigned int mode, unsigned int start, unsigned int end){
	start_ = start;
	end_ = end + 1;
	mode_ = mode;
	rotate_mode_idx_ = 1;
	
	if( mode_ != DEF_MODE_NON_MEMORY_ROTATE ){
		SAFE_DELETE( bitset_ );
		bitset_ = new BitField( end_ - start_ );
	}	
	
	if( start_ != 1 )
		weightValue_ = start_;
	else
		weightValue_ = 0;

	return true;
}

void UniqNumGenerater::reset(){	
	bitset_->reset();
}

size_t UniqNumGenerater::get_current_value(){
	return rotate_mode_idx_;
}

size_t UniqNumGenerater::get(){
    size_t retValue = 0;
	
	if( mode_ == DEF_MODE_ROTATE )
		retValue = getRotateFree();
	else if( mode_ == DEF_MODE_NON_MEMORY_ROTATE ){
		retValue = rotate_mode_idx_++;

		if( end_ < rotate_mode_idx_ )
			rotate_mode_idx_ = 1;
	}
	else
		retValue = getJamFree();

    return (retValue + weightValue_);
}

void UniqNumGenerater::free( unsigned int num ){
	if( mode_ == DEF_MODE_NON_MEMORY_ROTATE )
		return;

	if( end_ <= num ){
		LOG_ERR( LOG_SERVICE( "instance" )->Log("%s - end = %u - idx = %u ", end_, num ) );
		return;
	}

	if( num < weightValue_ ){
		LOG_ERR( LOG_SERVICE( "instance" )->Log("%s - weight = %u - idx = %u ", weightValue_, num ) );
		return;
	}

	num -= weightValue_;

	bitset_->setOff( num );	
}

size_t UniqNumGenerater::getRotateFree(){
	if( ( rotate_mode_idx_ + 1 ) >= end_ )
		rotate_mode_idx_ = 1;

	while( 1 ){
		if(! bitset_->isOn( rotate_mode_idx_ ) ){
			bitset_->setOn( rotate_mode_idx_ );
			return rotate_mode_idx_;
		}

		rotate_mode_idx_++;

		if( rotate_mode_idx_ >= end_ )
			break;
	}

	LOG_ERR( LOG_SERVICE( "instance" )->Log("%s - %u", __FUNCTION__, __LINE__ ) );	

	return 0;
}

size_t UniqNumGenerater::getJamFree(){
    for( size_t retValue = 1 ; retValue < end_ ; retValue++ ){		
		if(! bitset_->isOn( retValue ) ){
			bitset_->setOn( retValue );
			return retValue;
		}
    }

    return 0;
}